﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Sgr.Utilities;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using System.Web;

namespace Sgr.Identity.Services
{
    public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
    {
        private readonly HttpCookieOptions _httpCookieOptions;

        private const string XRequestedWith = "x-requested-with";
        private const string XMLHttpRequest = "XMLHttpRequest";

        public CustomCookieAuthenticationEvents(IOptions<IdentityOptions> options)
        {
            _httpCookieOptions = options?.Value?.Cookie ?? throw new ArgumentNullException(nameof(options));
        }

        public override async Task RedirectToLogin(RedirectContext<CookieAuthenticationOptions> context)
        {
            if (IsAjaxRequest(context.Request))
            {
                await HandleAjaxRedirect(context);
            }
            else
            {
                HandleStandardRedirect(context);
            }
        }

        public override Task ValidatePrincipal(CookieValidatePrincipalContext context)
        {
            //https://learn.microsoft.com/zh-cn/aspnet/core/security/authentication/cookie?view=aspnetcore-9.0

            //var userPrincipal = context.Principal;

            //// Look for the LastChanged claim.
            //var jti = (from c in userPrincipal?.Claims
            //           where c.Type == Constant.CLAIM_JTI
            //           select c.Value).FirstOrDefault();

            //if (balaba...根据令牌的唯一标识jti来判断用户状态是否发生变化，如若变化则退出登录){
            //    context.RejectPrincipal();

            //    await context.HttpContext.SignOutAsync(
            //        CookieAuthenticationDefaults.AuthenticationScheme);
            //}

            return base.ValidatePrincipal(context);
        }

        /// <summary>
        /// 检查请求是否为 Ajax 请求
        /// </summary>
        private static bool IsAjaxRequest(HttpRequest request)
            => request.Headers.TryGetValue(XRequestedWith, out var headerValue)
               && headerValue == XMLHttpRequest;

        /// <summary>
        /// 处理 Ajax 请求的重定向
        /// </summary>
        private static async Task HandleAjaxRedirect(RedirectContext<CookieAuthenticationOptions> context)
        {
            var payload = "{\"serviceerror\": { \"code\": 401,\"message\": \"未登录!\" } }";
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
            context.Response.ContentType = "application/json";
            await context.Response.WriteAsync(payload);
        }

        /// <summary>
        /// 处理标准的重定向
        /// </summary>
        private void HandleStandardRedirect(RedirectContext<CookieAuthenticationOptions> context)
        {
            var returnUrl = BuildReturnUrl(context.Request);
            var loginUrl = $"{_httpCookieOptions.LoginPath}?ReturnUrl={returnUrl}";
            context.Response.Redirect(loginUrl);
        }

        /// <summary>
        /// 构建返回URL
        /// </summary>
        private static string BuildReturnUrl(HttpRequest request)
            => HttpUtility.UrlEncode(request.Path + request.QueryString);
    }
}